import os
import re
import datetime
import folder_paths
import json



class TextDisplay:
    """
    文本显示器节点
    输入文本并显示，专门优化用于ComfyUI的文本显示
    """
    
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "text_input": ("STRING", {"default": "", "multiline": True, "forceInput": True}),
            },
            "optional": {
                "show_in_console": ("BOOLEAN", {"default": True, "tooltip": "是否在控制台显示"}),
                "add_line_numbers": ("BOOLEAN", {"default": False, "tooltip": "是否添加行号"}),
                "max_preview_length": ("STRING", {"default": "200", "multiline": False, "tooltip": "预览最大长度"}),
            },
        }

    RETURN_TYPES = ("STRING",)
    RETURN_NAMES = ("text_output",)
    FUNCTION = "display_text"
    OUTPUT_NODE = True
    CATEGORY = "AI训练/text"

    def display_text(self, text_input, show_in_console=True, add_line_numbers=False, max_preview_length="200"):
        # 参数验证和默认值处理
        try:
            max_preview_length = int(max_preview_length) if max_preview_length else 200
            if max_preview_length <= 0:
                max_preview_length = 200
        except (ValueError, TypeError):
            max_preview_length = 200
        """
        显示文本内容

        Args:
            text_input: 输入的文本
            show_in_console: 是否在控制台显示
            add_line_numbers: 是否添加行号
            max_preview_length: 预览最大长度

        Returns:
            dict: 包含UI数据和结果的字典
        """
        try:
            # 确保输入是字符串
            if not isinstance(text_input, str):
                text_input = str(text_input)

            # 在控制台显示文本
            if show_in_console:
                self._print_to_console(text_input, add_line_numbers)

            # 创建预览文本（用于UI显示）
            preview_text = self._create_preview(text_input, max_preview_length)

            # 生成统计信息
            stats = self._generate_text_stats(text_input)

            # 为前端提供数据 - 匹配JavaScript期望的格式
            return {
                "ui": {
                    "text_content": [text_input],
                    "text_stats": [stats],
                    "add_line_numbers": [add_line_numbers],
                },
                "result": (text_input,)
            }

        except Exception as e:
            error_msg = f"显示文本时出错: {str(e)}"
            return {
                "ui": {
                    "text_content": [error_msg],
                    "text_stats": [{"error": True}],
                    "add_line_numbers": [False],
                },
                "result": (error_msg,)
            }
    
    def _print_to_console(self, text, add_line_numbers):
        """在控制台打印文本"""
        try:
            print("\n" + "=" * 80)
            print("📺 文本显示器输出")
            print("=" * 80)
            
            if add_line_numbers:
                lines = text.split('\n')
                for i, line in enumerate(lines, 1):
                    print(f"{i:4d}: {line}")
            else:
                print(text)
            
            print("=" * 80)
            print(f"📊 统计信息:")
            print(f"   字符数: {len(text)}")
            print(f"   单词数: {len(text.split())}")
            
            # 计算行数（避免在f-string中使用反斜杠）
            line_count = len(text.split('\n'))
            print(f"   行数: {line_count}")
            print("=" * 80 + "\n")
            
        except Exception as e:
            print(f"控制台打印出错: {e}")
            print(f"原始文本: {text}")
    
    def _create_preview(self, text, max_length):
        """创建预览文本"""
        if len(text) <= max_length:
            return text
        else:
            return text[:max_length] + f"...\n\n[文本已截断，完整内容请查看控制台输出]"

    def _generate_text_stats(self, text):
        """生成文本统计信息"""
        try:
            lines = text.split('\n')
            words = text.split()

            # 计算字符统计
            char_count = len(text)
            char_count_no_spaces = len(text.replace(' ', '').replace('\n', '').replace('\t', ''))

            # 计算行统计
            line_count = len(lines)
            non_empty_lines = len([line for line in lines if line.strip()])

            # 计算单词统计
            word_count = len(words)

            # 计算段落统计（以空行分隔）
            paragraphs = [p.strip() for p in text.split('\n\n') if p.strip()]
            paragraph_count = len(paragraphs)

            return {
                "char_count": char_count,
                "char_count_no_spaces": char_count_no_spaces,
                "word_count": word_count,
                "line_count": line_count,
                "non_empty_lines": non_empty_lines,
                "paragraph_count": paragraph_count,
                "avg_words_per_line": round(word_count / max(non_empty_lines, 1), 1),
                "avg_chars_per_line": round(char_count / max(line_count, 1), 1),
            }
        except Exception as e:
            return {"error": str(e)}

class SaveTextToPath:
    """
    保存文本到指定路径的节点
    支持自定义目录、文件名和文件扩展名
    """

    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "text_content": ("STRING", {"default": "", "multiline": True, "tooltip": "要保存的文本内容"}),
                "output_directory": ("STRING", {"default": "", "multiline": False, "tooltip": "输出目录路径"}),
                "filename": ("STRING", {"default": "output", "multiline": False, "tooltip": "文件名（不含扩展名）"}),
            },
            "optional": {
                "file_extension": (["txt", "md", "json", "csv", "log", "xml", "html", "py", "js", "css"],
                                 {"default": "txt", "tooltip": "文件扩展名"}),
                "encoding": (["utf-8", "gbk", "ascii", "utf-16"], {"default": "utf-8", "tooltip": "文件编码"}),
                "add_timestamp": ("BOOLEAN", {"default": False, "tooltip": "是否在文件名中添加时间戳"}),
                "overwrite": ("BOOLEAN", {"default": True, "tooltip": "是否覆盖已存在的文件"}),
                "append_mode": ("BOOLEAN", {"default": False, "tooltip": "是否以追加模式写入（仅当文件存在时）"}),
            },
        }

    RETURN_TYPES = ("STRING", "STRING")
    RETURN_NAMES = ("saved_path", "output_info")
    FUNCTION = "save_text"
    OUTPUT_NODE = True
    CATEGORY = "AI训练/text"

    def save_text(self, text_content, output_directory, filename, file_extension="txt",
                 encoding="utf-8", add_timestamp=False, overwrite=False, append_mode=False):
        """
        保存文本到指定路径
        """
        try:
            # 运行时验证
            if not filename or not isinstance(filename, str):
                raise ValueError("文件名不能为空")

            # 验证文件扩展名
            valid_extensions = ["txt", "md", "json", "csv", "log", "xml", "html", "py", "js", "css"]
            if file_extension not in valid_extensions:
                raise ValueError(f"不支持的文件扩展名: {file_extension}")

            # 验证编码
            valid_encodings = ["utf-8", "gbk", "ascii", "utf-16"]
            if encoding not in valid_encodings:
                raise ValueError(f"不支持的编码: {encoding}")

            # 验证文本内容
            if not text_content:
                pass  # 允许空文本内容

            # 验证和创建输出目录
            if not output_directory:
                output_directory = folder_paths.get_output_directory()

            # 处理相对路径
            if not os.path.isabs(output_directory):
                output_directory = os.path.abspath(output_directory)

            # 创建目录（如果不存在）
            os.makedirs(output_directory, exist_ok=True)

            # 验证目录是否可写
            if not os.access(output_directory, os.W_OK):
                raise PermissionError(f"无法写入目录: {output_directory}")

            # 生成文件名
            final_filename = self._generate_text_filename(filename, add_timestamp, file_extension)
            full_path = os.path.join(output_directory, final_filename)

            # 处理文件存在的情况
            if os.path.exists(full_path):
                if append_mode and not overwrite:
                    # 追加模式
                    write_mode = 'a'
                    action = "追加到"
                elif overwrite:
                    # 覆盖模式
                    write_mode = 'w'
                    action = "覆盖"
                else:
                    # 添加数字后缀避免覆盖
                    base_name, ext = os.path.splitext(final_filename)
                    counter = 1
                    while os.path.exists(full_path):
                        final_filename = f"{base_name}_{counter:03d}{ext}"
                        full_path = os.path.join(output_directory, final_filename)
                        counter += 1
                    write_mode = 'w'
                    action = "保存到"
            else:
                write_mode = 'w'
                action = "保存到"

            # 保存文本文件
            with open(full_path, write_mode, encoding=encoding) as f:
                if append_mode and write_mode == 'a':
                    # 追加模式时添加分隔符
                    f.write(f"\n\n--- 添加于 {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} ---\n")
                f.write(text_content)

            # 获取文件信息
            file_size = os.path.getsize(full_path)
            file_size_str = self._format_file_size(file_size)

            # 生成输出信息
            output_info = self._generate_text_output_info(
                final_filename, full_path, file_size_str, encoding, action
            )

            return (full_path, output_info)

        except Exception as e:
            error_msg = f"保存文本时出错: {str(e)}"
            return ("", error_msg)

    def _generate_text_filename(self, base_filename, add_timestamp, file_extension):
        """生成最终的文件名"""
        # 清理文件名中的非法字符
        safe_filename = re.sub(r'[<>:"/\\|?*]', '_', base_filename)

        # 只有在明确要求时才添加时间戳
        if add_timestamp:
            timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            safe_filename += f"_{timestamp}"

        # 添加扩展名
        return f"{safe_filename}.{file_extension}"

    def _format_file_size(self, size_bytes):
        """格式化文件大小"""
        if size_bytes == 0:
            return "0 B"

        size_names = ["B", "KB", "MB", "GB"]
        i = 0
        while size_bytes >= 1024 and i < len(size_names) - 1:
            size_bytes /= 1024.0
            i += 1

        return f"{size_bytes:.1f} {size_names[i]}"

    def _generate_text_output_info(self, filename, full_path, file_size, encoding, action):
        """生成文本保存的输出信息"""
        info_lines = [
            f"文本文件保存信息",
            "=" * 40,
            f"文件名: {filename}",
            f"完整路径: {full_path}",
            f"文件大小: {file_size}",
            f"编码格式: {encoding}",
            f"操作类型: {action}",
            f"保存时间: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            "=" * 40
        ]

        return "\n".join(info_lines)



class SimpleTagEditor:
    """
    交互式标签编辑器
    显示所有标签按钮列表，支持添加、删除、修改操作
    """

    def __init__(self):
        self.tags_list = []
        self.folder_path = ""
        self.nsfw_config = self._load_nsfw_config()
        self.translation_config = self._load_translation_config()

    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "folder_path": ("STRING", {"default": "", "multiline": False, "tooltip": "文本文件所在的文件夹路径"}),
            },
            "optional": {
                "separator": (["逗号", "分号", "空格", "换行"], {"default": "逗号", "tooltip": "文本分割符"}),
                "file_extensions": ("STRING", {"default": "txt,md,csv", "multiline": False, "tooltip": "要读取的文件扩展名"}),
                "encoding": (["utf-8", "gbk", "ascii", "utf-16"], {"default": "utf-8", "tooltip": "文件编码"}),
                "refresh": ("BOOLEAN", {"default": False, "tooltip": "刷新文件"}),
                "selected_file": ("STRING", {"default": "", "multiline": False, "tooltip": "选择的文件"}),
                "operation": ("STRING", {"default": "加载文件", "multiline": False, "tooltip": "操作类型"}),
                "new_tag": ("STRING", {"default": "", "multiline": False, "tooltip": "新标签"}),
                "target_tag": ("STRING", {"default": "", "multiline": False, "tooltip": "目标标签"}),
            },
        }

    RETURN_TYPES = ("LIST", "STRING", "INT", "STRING")
    RETURN_NAMES = ("tags_list", "tags_display", "total_count", "operation_result")
    FUNCTION = "edit_tags"
    OUTPUT_NODE = True
    CATEGORY = "AI训练/text"

    @classmethod
    def IS_CHANGED(cls, **kwargs):
        # 强制每次都更新显示
        return float("nan")



    def edit_tags(self, folder_path, separator="逗号", file_extensions="txt,md,csv",
                 encoding="utf-8", refresh=False, selected_file="", operation="加载文件",
                 new_tag="", target_tag=""):
        """
        编辑标签
        """
        try:
            # 确保参数有效
            if not operation or operation not in ["加载文件", "添加标签", "删除标签", "修改标签"]:
                operation = "加载文件"

            operation_result = ""

            # 首先确保数据已加载
            if not hasattr(self, 'file_list') or self.folder_path != folder_path or refresh:
                if not folder_path or not os.path.exists(folder_path):
                    return ([], "错误: 文件夹路径不存在或为空", 0, "请提供有效的文件夹路径")

                self.folder_path = folder_path

                # 一次性获取所有信息
                self.file_list = self._get_file_list(folder_path, file_extensions)
                self.all_tags = self._load_tags_from_files(folder_path, file_extensions, encoding, separator)
                self.file_tags_cache = self._load_all_file_tags(folder_path, file_extensions, encoding, separator)

            # 根据操作类型执行不同逻辑
            if operation == "加载文件":
                operation_result = f"✅ 成功加载 {len(self.file_list)} 个文件，共 {len(self.all_tags)} 个唯一标签"

            # 添加标签操作
            elif operation == "添加标签":
                if new_tag and new_tag.strip():
                    new_tag = new_tag.strip()

                    # 检查位置前缀
                    add_position = "最后面"
                    if new_tag.startswith("__FRONT__"):
                        actual_tag = new_tag[9:]  # 移除 "__FRONT__" 前缀
                        add_position = "最前面"
                    else:
                        actual_tag = new_tag

                    if selected_file and selected_file != "所有文件":
                        # 单个文件操作
                        operation_result = self._add_tag_to_single_file(
                            folder_path, file_extensions, encoding, separator,
                            actual_tag, add_position, selected_file
                        )
                        # 更新缓存
                        file_tags, _ = self._get_file_tags(
                            folder_path, file_extensions, encoding, separator, selected_file
                        )
                        self.file_tags_cache[selected_file] = file_tags
                        self.all_tags = self._load_tags_from_files(
                            folder_path, file_extensions, encoding, separator
                        )
                    else:
                        # 所有文件操作
                        operation_result = self._add_tag_to_files(
                            folder_path, file_extensions, encoding, separator,
                            actual_tag, add_position
                        )
                        # 重新加载缓存
                        self.all_tags = self._load_tags_from_files(
                            folder_path, file_extensions, encoding, separator
                        )
                        self.file_tags_cache = self._load_all_file_tags(
                            folder_path, file_extensions, encoding, separator
                        )
                else:
                    operation_result = "❌ 请输入要添加的标签"

            # 删除标签操作
            elif operation == "删除标签":
                if target_tag and target_tag.strip():
                    tags_to_delete = [tag.strip() for tag in target_tag.split(',') if tag.strip()]

                    if selected_file and selected_file != "所有文件":
                        # 单个文件操作
                        operation_result = self._remove_tags_from_single_file(
                            folder_path, file_extensions, encoding, separator,
                            tags_to_delete, selected_file
                        )
                        # 更新缓存
                        file_tags, _ = self._get_file_tags(
                            folder_path, file_extensions, encoding, separator, selected_file
                        )
                        self.file_tags_cache[selected_file] = file_tags
                        self.all_tags = self._load_tags_from_files(
                            folder_path, file_extensions, encoding, separator
                        )
                    else:
                        # 所有文件操作
                        operation_result = self._remove_tags_from_files(
                            folder_path, file_extensions, encoding, separator, tags_to_delete
                        )
                        # 重新加载缓存
                        self.all_tags = self._load_tags_from_files(
                            folder_path, file_extensions, encoding, separator
                        )
                        self.file_tags_cache = self._load_all_file_tags(
                            folder_path, file_extensions, encoding, separator
                        )
                else:
                    operation_result = "❌ 请输入要删除的标签"

            # 修改标签操作
            elif operation == "修改标签":
                if target_tag and target_tag.strip() and new_tag and new_tag.strip():
                    target_tag = target_tag.strip()
                    new_tag = new_tag.strip()

                    if selected_file and selected_file != "所有文件":
                        # 单个文件操作
                        operation_result = self._replace_tag_in_single_file(
                            folder_path, file_extensions, encoding, separator,
                            target_tag, new_tag, selected_file
                        )
                        # 更新缓存
                        file_tags, _ = self._get_file_tags(
                            folder_path, file_extensions, encoding, separator, selected_file
                        )
                        self.file_tags_cache[selected_file] = file_tags
                        self.all_tags = self._load_tags_from_files(
                            folder_path, file_extensions, encoding, separator
                        )
                    else:
                        # 所有文件操作
                        operation_result = self._replace_tag_in_files(
                            folder_path, file_extensions, encoding, separator,
                            target_tag, new_tag
                        )
                        # 重新加载缓存
                        self.all_tags = self._load_tags_from_files(
                            folder_path, file_extensions, encoding, separator
                        )
                        self.file_tags_cache = self._load_all_file_tags(
                            folder_path, file_extensions, encoding, separator
                        )
                else:
                    operation_result = "❌ 请提供有效的目标标签和新标签"

            # 根据选择的文件显示标签
            if selected_file and selected_file != "所有文件" and hasattr(self, 'file_tags_cache'):
                self.tags_list = self.file_tags_cache.get(selected_file, [])
            else:
                if hasattr(self, 'all_tags'):
                    self.tags_list = self.all_tags

            # 生成标签显示
            tags_display = self._generate_interactive_display()

            # 分析标签的NSFW状态
            tags_with_nsfw_info = self._analyze_tags_nsfw_status(self.tags_list)

            # 获取标签翻译
            tag_translations = self._get_tag_translations(self.tags_list)

            # 为JavaScript提供数据
            file_list_with_all = ["所有文件"] + getattr(self, 'file_list', [])

            return {
                "ui": {
                    "tags_list": [self.tags_list],
                    "tags_nsfw_info": [tags_with_nsfw_info],
                    "tag_translations": [tag_translations],
                    "file_list": [file_list_with_all],
                    "current_file": [selected_file or "所有文件"],
                },
                "result": (self.tags_list, tags_display, len(self.tags_list), operation_result)
            }

        except Exception as e:
            error_msg = f"编辑标签时出错: {str(e)}"
            return ([], error_msg, 0, error_msg)

    # 公共方法供JavaScript调用
    def add_tag(self, new_tag, add_to_front=False, selected_file="所有文件"):
        """添加标签的公共方法"""
        if not hasattr(self, 'folder_path'):
            return "❌ 请先加载文件"

        add_position = "最前面" if add_to_front else "最后面"

        if selected_file and selected_file != "所有文件":
            # 单个文件操作
            result = self._add_tag_to_single_file(
                self.folder_path, "txt,md,csv", "utf-8", "逗号",
                new_tag, add_position, selected_file
            )
            # 更新缓存
            file_tags, _ = self._get_file_tags(
                self.folder_path, "txt,md,csv", "utf-8", "逗号", selected_file
            )
            self.file_tags_cache[selected_file] = file_tags
            self.all_tags = self._load_tags_from_files(
                self.folder_path, "txt,md,csv", "utf-8", "逗号"
            )
        else:
            # 所有文件操作
            result = self._add_tag_to_files(
                self.folder_path, "txt,md,csv", "utf-8", "逗号",
                new_tag, add_position
            )
            # 重新加载缓存
            self.all_tags = self._load_tags_from_files(
                self.folder_path, "txt,md,csv", "utf-8", "逗号"
            )
            self.file_tags_cache = self._load_all_file_tags(
                self.folder_path, "txt,md,csv", "utf-8", "逗号"
            )

        return result

    def remove_tags(self, tags_to_remove, selected_file="所有文件"):
        """删除标签的公共方法"""
        if not hasattr(self, 'folder_path'):
            return "❌ 请先加载文件"

        if isinstance(tags_to_remove, str):
            tags_to_remove = [tag.strip() for tag in tags_to_remove.split(',') if tag.strip()]

        if selected_file and selected_file != "所有文件":
            # 单个文件操作
            result = self._remove_tags_from_single_file(
                self.folder_path, "txt,md,csv", "utf-8", "逗号",
                tags_to_remove, selected_file
            )
            # 更新缓存
            file_tags, _ = self._get_file_tags(
                self.folder_path, "txt,md,csv", "utf-8", "逗号", selected_file
            )
            self.file_tags_cache[selected_file] = file_tags
            self.all_tags = self._load_tags_from_files(
                self.folder_path, "txt,md,csv", "utf-8", "逗号"
            )
        else:
            # 所有文件操作
            result = self._remove_tags_from_files(
                self.folder_path, "txt,md,csv", "utf-8", "逗号", tags_to_remove
            )
            # 重新加载缓存
            self.all_tags = self._load_tags_from_files(
                self.folder_path, "txt,md,csv", "utf-8", "逗号"
            )
            self.file_tags_cache = self._load_all_file_tags(
                self.folder_path, "txt,md,csv", "utf-8", "逗号"
            )

        return result

    def switch_file(self, selected_file="所有文件"):
        """切换文件的公共方法"""
        if not hasattr(self, 'file_tags_cache') or not hasattr(self, 'all_tags'):
            return "❌ 请先加载文件"

        if selected_file and selected_file != "所有文件":
            self.tags_list = self.file_tags_cache.get(selected_file, [])
            return f"✅ 切换到文件 '{selected_file}'，显示 {len(self.tags_list)} 个标签"
        else:
            self.tags_list = self.all_tags
            return f"✅ 切换到所有文件，显示 {len(self.tags_list)} 个唯一标签"

    def _load_tags_from_files(self, folder_path, file_extensions, encoding, separator):
        """从文件夹加载所有标签"""
        all_tags = []
        extensions = [ext.strip().lower() for ext in file_extensions.split(',')]

        # 分割符映射
        separator_map = {
            "逗号": ",",
            "分号": ";",
            "空格": " ",
            "换行": "\n"
        }
        sep = separator_map.get(separator, ",")

        file_count = 0
        for root, dirs, files in os.walk(folder_path):
            for file in files:
                file_ext = os.path.splitext(file)[1][1:].lower()
                if file_ext in extensions:
                    file_path = os.path.join(root, file)
                    try:
                        with open(file_path, 'r', encoding=encoding) as f:
                            content = f.read().strip()
                            if content:
                                # 根据分割符分割文本
                                if sep == "\n":
                                    tags = content.split('\n')
                                else:
                                    tags = content.split(sep)

                                # 清理标签
                                cleaned_tags = [tag.strip() for tag in tags if tag.strip()]
                                all_tags.extend(cleaned_tags)
                                file_count += 1

                    except Exception as e:
                        pass  # 忽略读取错误的文件

        # 去重并排序
        unique_tags = sorted(list(set(all_tags)))

        return unique_tags

    def _generate_interactive_display(self):
        """生成交互式显示内容"""
        if not self.tags_list:
            return """
🏷️ 交互式标签编辑器
=====================================
❌ 没有加载任何标签

📁 请先设置文件夹路径并选择'加载文件'操作
"""

        # 创建标签网格显示
        display_lines = [
            "🏷️ 交互式标签编辑器",
            f"📊 当前标签数量: {len(self.tags_list)}",
            "=" * 100,
            ""
        ]

        # 按网格显示标签，每行3个
        for i in range(0, len(self.tags_list), 3):
            row_tags = self.tags_list[i:i+3]
            row_display = []

            for j, tag in enumerate(row_tags):
                tag_num = i + j + 1
                # 创建标签按钮样式的显示
                if len(tag) <= 30:
                    display_tag = tag
                else:
                    display_tag = tag[:27] + "..."

                # 格式化为按钮样式
                tag_button = f"[{tag_num:3d}] {display_tag:<30}"
                row_display.append(tag_button)

            # 填充空位
            while len(row_display) < 3:
                row_display.append(" " * 35)

            display_lines.append("  ".join(row_display))

        display_lines.extend([
            "",
            "=" * 100,
            "🛠️ 快速操作指南:",
            "",
            "1️⃣ 加载标签:",
            "   operation='加载文件' → 点击运行",
            "",
            "2️⃣ 添加新标签:",
            "   operation='添加标签' + new_tag='新标签名' → 点击运行",
            "",
            "3️⃣ 删除标签:",
            "   operation='删除标签' + target_tag='要删除的标签' → 点击运行",
            "",
            "4️⃣ 修改标签:",
            "   operation='修改标签' + target_tag='原标签' + new_tag='新标签' → 点击运行",
            "",
            "💡 提示: 直接复制上面的标签名到 target_tag 输入框",
            f"📝 当前共有 {len(self.tags_list)} 个标签"
        ])

        return "\n".join(display_lines)

    def _add_tag_to_files(self, folder_path, file_extensions, encoding, separator, new_tag, add_position):
        """向所有文件添加标签"""
        try:
            extensions = [ext.strip().lower() for ext in file_extensions.split(',')]
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            modified_files = 0
            total_files = 0

            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    file_ext = os.path.splitext(file)[1][1:].lower()
                    if file_ext in extensions:
                        file_path = os.path.join(root, file)
                        total_files += 1

                        try:
                            # 读取文件内容
                            with open(file_path, 'r', encoding=encoding) as f:
                                content = f.read().strip()

                            if content:
                                # 解析现有标签
                                if sep == "\n":
                                    existing_tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                                else:
                                    existing_tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                                # 检查标签是否已存在
                                if new_tag not in existing_tags:
                                    # 根据位置添加标签
                                    if add_position == "最前面":
                                        existing_tags.insert(0, new_tag)
                                    else:  # 最后面
                                        existing_tags.append(new_tag)

                                    # 重新组合内容
                                    if sep == "\n":
                                        new_content = '\n'.join(existing_tags)
                                    else:
                                        new_content = sep.join(existing_tags)

                                    # 写回文件
                                    with open(file_path, 'w', encoding=encoding) as f:
                                        f.write(new_content)

                                    modified_files += 1
                            else:
                                # 空文件，直接写入新标签
                                with open(file_path, 'w', encoding=encoding) as f:
                                    f.write(new_tag)
                                modified_files += 1

                        except Exception as e:
                            pass  # 忽略处理错误的文件

            return f"✅ 成功添加标签 '{new_tag}' 到 {modified_files}/{total_files} 个文件"

        except Exception as e:
            return f"❌ 添加标签时出错: {str(e)}"

    def _remove_tags_from_files(self, folder_path, file_extensions, encoding, separator, tags_to_remove):
        """从所有文件中删除指定标签"""
        try:
            extensions = [ext.strip().lower() for ext in file_extensions.split(',')]
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            modified_files = 0
            total_files = 0
            removed_count = 0

            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    file_ext = os.path.splitext(file)[1][1:].lower()
                    if file_ext in extensions:
                        file_path = os.path.join(root, file)
                        total_files += 1

                        try:
                            # 读取文件内容
                            with open(file_path, 'r', encoding=encoding) as f:
                                content = f.read().strip()

                            if content:
                                # 解析现有标签
                                if sep == "\n":
                                    existing_tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                                else:
                                    existing_tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                                # 删除指定标签
                                original_count = len(existing_tags)
                                existing_tags = [tag for tag in existing_tags if tag not in tags_to_remove]

                                # 如果有标签被删除
                                if len(existing_tags) < original_count:
                                    removed_count += original_count - len(existing_tags)

                                    # 重新组合内容
                                    if existing_tags:
                                        if sep == "\n":
                                            new_content = '\n'.join(existing_tags)
                                        else:
                                            new_content = sep.join(existing_tags)
                                    else:
                                        new_content = ""  # 如果没有标签了，清空文件

                                    # 写回文件
                                    with open(file_path, 'w', encoding=encoding) as f:
                                        f.write(new_content)

                                    modified_files += 1

                        except Exception as e:
                            pass  # 忽略处理错误的文件

            if removed_count > 0:
                return f"✅ 成功从 {modified_files}/{total_files} 个文件中删除了 {removed_count} 个标签实例"
            else:
                return f"⚠️ 在 {total_files} 个文件中未找到要删除的标签: {', '.join(tags_to_remove)}"

        except Exception as e:
            return f"❌ 删除标签时出错: {str(e)}"

    def _replace_tag_in_files(self, folder_path, file_extensions, encoding, separator, target_tag, new_tag):
        """在包含目标标签的文件中替换标签"""
        try:
            extensions = [ext.strip().lower() for ext in file_extensions.split(',')]
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            modified_files = 0
            total_files = 0
            replaced_count = 0

            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    file_ext = os.path.splitext(file)[1][1:].lower()
                    if file_ext in extensions:
                        file_path = os.path.join(root, file)
                        total_files += 1

                        try:
                            # 读取文件内容
                            with open(file_path, 'r', encoding=encoding) as f:
                                content = f.read().strip()

                            if content:
                                # 解析现有标签
                                if sep == "\n":
                                    existing_tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                                else:
                                    existing_tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                                # 检查是否包含目标标签
                                if target_tag in existing_tags:
                                    # 检查新标签是否已存在
                                    if new_tag not in existing_tags:
                                        # 替换标签
                                        existing_tags = [new_tag if tag == target_tag else tag for tag in existing_tags]
                                        replaced_count += 1

                                        # 重新组合内容
                                        if sep == "\n":
                                            new_content = '\n'.join(existing_tags)
                                        else:
                                            new_content = sep.join(existing_tags)

                                        # 写回文件
                                        with open(file_path, 'w', encoding=encoding) as f:
                                            f.write(new_content)

                                        modified_files += 1
                                    else:
                                        # 新标签已存在，只删除旧标签
                                        existing_tags = [tag for tag in existing_tags if tag != target_tag]

                                        # 重新组合内容
                                        if sep == "\n":
                                            new_content = '\n'.join(existing_tags)
                                        else:
                                            new_content = sep.join(existing_tags)

                                        # 写回文件
                                        with open(file_path, 'w', encoding=encoding) as f:
                                            f.write(new_content)

                                        modified_files += 1

                        except Exception as e:
                            pass  # 忽略处理错误的文件

            if replaced_count > 0:
                return f"✅ 成功在 {modified_files}/{total_files} 个文件中将 '{target_tag}' 替换为 '{new_tag}'"
            elif modified_files > 0:
                return f"⚠️ 在 {modified_files} 个文件中删除了重复的 '{target_tag}'（因为 '{new_tag}' 已存在）"
            else:
                return f"⚠️ 在 {total_files} 个文件中未找到标签: '{target_tag}'"

        except Exception as e:
            return f"❌ 修改标签时出错: {str(e)}"

    def _get_file_list(self, folder_path, file_extensions):
        """获取文件夹中的所有文件列表"""
        try:
            extensions = [ext.strip().lower() for ext in file_extensions.split(',')]
            file_list = []

            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    file_ext = os.path.splitext(file)[1][1:].lower()
                    if file_ext in extensions:
                        # 使用相对路径
                        rel_path = os.path.relpath(os.path.join(root, file), folder_path)
                        file_list.append(rel_path)

            return sorted(file_list)
        except Exception as e:
            return []

    def _get_file_tags(self, folder_path, file_extensions, encoding, separator, selected_file):
        """获取单个文件的标签"""
        try:
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            file_path = os.path.join(folder_path, selected_file)

            if not os.path.exists(file_path):
                return [], f"❌ 文件不存在: {selected_file}"

            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read().strip()

            if content:
                if sep == "\n":
                    tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                else:
                    tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                return tags, f"✅ 成功读取文件 '{selected_file}' 的 {len(tags)} 个标签"
            else:
                return [], f"⚠️ 文件 '{selected_file}' 为空"

        except Exception as e:
            return [], f"❌ 读取文件时出错: {str(e)}"

    def _replace_tag_in_single_file(self, folder_path, file_extensions, encoding, separator, target_tag, new_tag, selected_file):
        """在单个文件中替换标签"""
        try:
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            file_path = os.path.join(folder_path, selected_file)

            if not os.path.exists(file_path):
                return f"❌ 文件不存在: {selected_file}"

            # 读取文件内容
            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read().strip()

            if content:
                # 解析现有标签
                if sep == "\n":
                    existing_tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                else:
                    existing_tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                # 检查是否包含目标标签
                if target_tag in existing_tags:
                    # 检查新标签是否已存在
                    if new_tag not in existing_tags:
                        # 替换标签
                        existing_tags = [new_tag if tag == target_tag else tag for tag in existing_tags]

                        # 重新组合内容
                        if sep == "\n":
                            new_content = '\n'.join(existing_tags)
                        else:
                            new_content = sep.join(existing_tags)

                        # 写回文件
                        with open(file_path, 'w', encoding=encoding) as f:
                            f.write(new_content)

                        return f"✅ 成功在文件 '{selected_file}' 中将 '{target_tag}' 替换为 '{new_tag}'"
                    else:
                        # 新标签已存在，只删除旧标签
                        existing_tags = [tag for tag in existing_tags if tag != target_tag]

                        # 重新组合内容
                        if sep == "\n":
                            new_content = '\n'.join(existing_tags)
                        else:
                            new_content = sep.join(existing_tags)

                        # 写回文件
                        with open(file_path, 'w', encoding=encoding) as f:
                            f.write(new_content)

                        return f"⚠️ 在文件 '{selected_file}' 中删除了重复的 '{target_tag}'（因为 '{new_tag}' 已存在）"
                else:
                    return f"⚠️ 在文件 '{selected_file}' 中未找到标签: '{target_tag}'"
            else:
                return f"⚠️ 文件 '{selected_file}' 为空"

        except Exception as e:
            return f"❌ 修改文件时出错: {str(e)}"

    def _add_tag_to_single_file(self, folder_path, file_extensions, encoding, separator, new_tag, add_position, selected_file):
        """向单个文件添加标签"""
        try:
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            file_path = os.path.join(folder_path, selected_file)

            if not os.path.exists(file_path):
                return f"❌ 文件不存在: {selected_file}"

            # 读取文件内容
            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read().strip()

            if content:
                # 解析现有标签
                if sep == "\n":
                    existing_tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                else:
                    existing_tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                # 检查标签是否已存在
                if new_tag not in existing_tags:
                    # 根据位置添加标签
                    if add_position == "最前面":
                        existing_tags.insert(0, new_tag)
                    else:  # 最后面
                        existing_tags.append(new_tag)

                    # 重新组合内容
                    if sep == "\n":
                        new_content = '\n'.join(existing_tags)
                    else:
                        new_content = sep.join(existing_tags)

                    # 写回文件
                    with open(file_path, 'w', encoding=encoding) as f:
                        f.write(new_content)

                    return f"✅ 成功向文件 '{selected_file}' 添加标签 '{new_tag}'"
                else:
                    return f"⚠️ 标签 '{new_tag}' 在文件 '{selected_file}' 中已存在"
            else:
                # 空文件，直接写入新标签
                with open(file_path, 'w', encoding=encoding) as f:
                    f.write(new_tag)
                return f"✅ 成功向空文件 '{selected_file}' 添加标签 '{new_tag}'"

        except Exception as e:
            return f"❌ 向文件添加标签时出错: {str(e)}"

    def _remove_tags_from_single_file(self, folder_path, file_extensions, encoding, separator, tags_to_remove, selected_file):
        """从单个文件中删除指定标签"""
        try:
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            file_path = os.path.join(folder_path, selected_file)

            if not os.path.exists(file_path):
                return f"❌ 文件不存在: {selected_file}"

            # 读取文件内容
            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read().strip()

            if content:
                # 解析现有标签
                if sep == "\n":
                    existing_tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                else:
                    existing_tags = [tag.strip() for tag in content.split(sep) if tag.strip()]

                # 删除指定标签
                original_count = len(existing_tags)
                existing_tags = [tag for tag in existing_tags if tag not in tags_to_remove]
                removed_count = original_count - len(existing_tags)

                if removed_count > 0:
                    # 重新组合内容
                    if existing_tags:
                        if sep == "\n":
                            new_content = '\n'.join(existing_tags)
                        else:
                            new_content = sep.join(existing_tags)
                    else:
                        new_content = ""  # 如果没有标签了，清空文件

                    # 写回文件
                    with open(file_path, 'w', encoding=encoding) as f:
                        f.write(new_content)

                    return f"✅ 成功从文件 '{selected_file}' 中删除了 {removed_count} 个标签"
                else:
                    return f"⚠️ 在文件 '{selected_file}' 中未找到要删除的标签: {', '.join(tags_to_remove)}"
            else:
                return f"⚠️ 文件 '{selected_file}' 为空"

        except Exception as e:
            return f"❌ 从文件删除标签时出错: {str(e)}"

    def _load_all_file_tags(self, folder_path, file_extensions, encoding, separator):
        """加载所有文件的标签，返回文件名到标签列表的映射"""
        try:
            separator_map = {
                "逗号": ",",
                "分号": ";",
                "空格": " ",
                "换行": "\n"
            }
            sep = separator_map.get(separator, ",")

            extensions = [ext.strip().lower() for ext in file_extensions.split(',')]
            file_tags_map = {}

            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    file_ext = os.path.splitext(file)[1][1:].lower()
                    if file_ext in extensions:
                        file_path = os.path.join(root, file)
                        rel_path = os.path.relpath(file_path, folder_path)

                        try:
                            with open(file_path, 'r', encoding=encoding) as f:
                                content = f.read().strip()

                            if content:
                                if sep == "\n":
                                    tags = [tag.strip() for tag in content.split('\n') if tag.strip()]
                                else:
                                    tags = [tag.strip() for tag in content.split(sep) if tag.strip()]
                                file_tags_map[rel_path] = tags
                            else:
                                file_tags_map[rel_path] = []
                        except Exception as e:
                            file_tags_map[rel_path] = []

            return file_tags_map
        except Exception as e:
            return {}

    def _load_nsfw_config(self):
        """加载NSFW配置文件"""
        try:
            # 获取当前文件所在目录
            current_dir = os.path.dirname(os.path.abspath(__file__))
            config_path = os.path.join(current_dir, "configs", "nsfw_prompts.json")

            if os.path.exists(config_path):
                with open(config_path, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    return config
            else:
                # 返回默认配置
                return {
                    "categories": {},
                    "severity_levels": {
                        "high": {"marker": "🔴", "categories": []},
                        "medium": {"marker": "🟡", "categories": []},
                        "low": {"marker": "🟠", "categories": []}
                    },
                    "settings": {
                        "case_sensitive": False,
                        "partial_match": True
                    }
                }
        except Exception as e:
            return {"categories": {}, "severity_levels": {}, "settings": {}}

    def _load_translation_config(self):
        """加载翻译配置文件"""
        try:
            # 获取当前文件所在目录
            current_dir = os.path.dirname(os.path.abspath(__file__))
            config_path = os.path.join(current_dir, "configs", "tag_translations.json")

            if os.path.exists(config_path):
                with open(config_path, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    return config
            else:
                # 返回默认配置
                return {
                    "translations": {},
                    "settings": {
                        "show_translation": True,
                        "translation_position": "tooltip",
                        "fallback_enabled": True
                    }
                }
        except Exception as e:
            return {"translations": {}, "settings": {}}

    def _analyze_tags_nsfw_status(self, tags_list):
        """分析标签的NSFW状态"""
        if not self.nsfw_config or not tags_list:
            return {}

        tags_nsfw_info = {}
        categories = self.nsfw_config.get("categories", {})
        severity_levels = self.nsfw_config.get("severity_levels", {})
        settings = self.nsfw_config.get("settings", {})

        case_sensitive = settings.get("case_sensitive", False)
        partial_match = settings.get("partial_match", True)

        for tag in tags_list:
            tag_info = {
                "is_nsfw": False,
                "category": None,
                "severity": None,
                "marker": None
            }

            # 检查每个类别
            for category_name, category_data in categories.items():
                keywords = category_data.get("keywords", [])

                for keyword in keywords:
                    # 根据设置进行匹配
                    if case_sensitive:
                        tag_to_check = tag
                        keyword_to_check = keyword
                    else:
                        tag_to_check = tag.lower()
                        keyword_to_check = keyword.lower()

                    # 检查匹配
                    is_match = False
                    if partial_match:
                        is_match = keyword_to_check in tag_to_check
                    else:
                        is_match = keyword_to_check == tag_to_check

                    if is_match:
                        tag_info["is_nsfw"] = True
                        tag_info["category"] = category_name

                        # 确定严重程度
                        for severity, severity_data in severity_levels.items():
                            if category_name in severity_data.get("categories", []):
                                tag_info["severity"] = severity
                                tag_info["marker"] = severity_data.get("marker", "⚠️")
                                break

                        break

                if tag_info["is_nsfw"]:
                    break

            tags_nsfw_info[tag] = tag_info

        return tags_nsfw_info

    def _get_tag_translations(self, tags_list):
        """获取标签的中文翻译"""
        if not self.translation_config or not tags_list:
            return {}

        translations = self.translation_config.get("translations", {})
        settings = self.translation_config.get("settings", {})

        tag_translations = {}
        for tag in tags_list:
            translation = None

            # 1. 直接匹配
            if tag in translations:
                translation = translations[tag]
            # 2. 小写匹配
            elif tag.lower() in translations:
                translation = translations[tag.lower()]
            # 3. 下划线分隔标签智能匹配
            elif settings.get("word_split_enabled", True) and '_' in tag:
                translation = self._get_compound_translation(tag, translations)
            # 4. 如果启用了fallback，尝试部分匹配
            elif settings.get("fallback_enabled", True):
                translation = self._get_partial_translation(tag, translations)

            if translation:
                tag_translations[tag] = translation

        return tag_translations

    def _get_compound_translation(self, tag, translations):
        """处理下划线分隔的复合标签翻译"""
        # 分割标签
        parts = tag.lower().split('_')
        translated_parts = []

        # 尝试翻译每个部分
        for part in parts:
            if part in translations:
                translated_parts.append(translations[part])
            else:
                # 如果某个部分没有翻译，保留原文
                translated_parts.append(part)

        # 如果所有部分都有翻译，组合返回
        if len(translated_parts) == len(parts) and any(p != parts[i] for i, p in enumerate(translated_parts)):
            return ''.join(translated_parts)

        return None

    def _get_partial_translation(self, tag, translations):
        """部分匹配翻译"""
        tag_lower = tag.lower()

        # 尝试找到包含该标签的翻译
        for trans_key, trans_value in translations.items():
            if tag_lower in trans_key.lower() or trans_key.lower() in tag_lower:
                return trans_value

        return None


# 节点类映射
NODE_CLASS_MAPPINGS = {
    "TextDisplay": TextDisplay,
    "SaveTextToPath": SaveTextToPath,
    "SimpleTagEditor": SimpleTagEditor,
}

NODE_DISPLAY_NAME_MAPPINGS = {
    "TextDisplay": "📺 文本显示器",
    "SaveTextToPath": "💾 保存文本到路径",
    "SimpleTagEditor": "🏷️ 简洁标签编辑器",
}
